<template>
  <div class="role-manage-box">
    <!-- 顶部标题、保存按钮 -->
    <div class="top-box">
      <div class="top">
        <span>角色管理</span>
        <el-form v-show="isShowForm" :model="formData" label-width="auto" inline
          style="height: 100%; vertical-align: middle;">
          <el-form-item label="角色名称：">
            <el-input v-model="formData.name" placeholder="请输入角色名称" style="width: 200px;" />
          </el-form-item>
          <el-form-item label="角色分组：">
            <el-input v-model="formData.group" placeholder="角色分组" style="width: 200px;" />
          </el-form-item>
        </el-form>
        <button v-show="!isShowForm" @click="isShowForm = true">+新增角色</button>
        <button v-show="isShowForm && !formData._id" @click="onConfirm"
          style="background-color: rgb(199, 138, 199);">确认新增</button>
        <button v-show="isShowForm && formData._id" @click="onConfirm"
          style="background-color: rgb(199, 138, 199);">确认修改</button>
      </div>
      <button class="cancel-btn" @click="onCancelBtnClick">取消</button>
    </div>
    <!-- 角色、角色权限 -->
    <div class="role-content">
      <div class="role">
        <div class="title-box">
          <span class="text">角色</span>
        </div>
        <div class="list">
          <div class="item" v-for="item in rolesData" :key="item._id" :class="{ bGColor: currentRole == item._id }">
            <span @click="onRoleClick(item)">{{ item.name }}</span>
            <div class="icon-box">
              <img class="write-img" src="../../assets//write.png" alt="" @click="onUpdateBtnClick(item)">
              <img src="../../assets/lajitong.png" alt="" @click="onDelBtnClick(item._id)">
            </div>
          </div>
        </div>
      </div>
      <div class="permission">
        <div class="text">管理角色权限</div>
        <div style=" width: 100%; display: flex; align-items: flex-start; ">
          <div style="flex-grow: 1; height: calc(100vh - 300px); overflow-y: scroll;">
            <el-tree ref="treeRef" show-checkbox :data="permissionData.rows" node-key="_id" :props="{ label: 'title' }"
              :check-strictly="true" @check="handleCheckChange" />
          </div>
          <el-button type="primary" link @click="onExpandToggle">
            {{ isExpand ? '收起' : '展开' }}
          </el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { addRoleApi, deleteRoleApi, getRolesApi, updateRoleApi } from '@/api/role';
import { useFindData } from '@/composables/findData';
import { nextTick, onMounted, ref, useTemplateRef, watch } from 'vue';

const currentRole = ref('');

const rolesData: any = ref([]);

const { open, findPermissionAsync, permissionData } = useFindData();

const treeRef = useTemplateRef('treeRef');

const isExpand = ref(false);

const formData = ref<any>({});

const isShowForm = ref(false);



onMounted(() => {
  getRoles();
  findPermissionAsync();
})



// 事件：删除按钮点击
const onDelBtnClick = async (_id: string) => {
  const isDel = await open();
  // 点击确认
  if (isDel) {
    delRole(_id);
  }
}

// 请求：删除角色
const delRole = async (_id: string) => {
  const res = await deleteRoleApi({ _id });
  if (res.code == 200) {
    ElMessage.success('删除成功');
    onCancelBtnClick();
    getRoles();
  } else {
    ElMessage.error(res.message);
  }
}

// 事件：取消按钮点击事件
const onCancelBtnClick = () => {
  formData.value = {};
  isShowForm.value = false;
  treeRef.value?.setCheckedKeys([]);
  isExpand.value = false;
};

// 事件：修改按钮点击
const onUpdateBtnClick = (item: any) => {
  isShowForm.value = true;
  formData.value = { ...item };
  treeBackShow(item);
}

// 事件：确认 添加 / 修改 按钮点击
const onConfirm = () => {
  // 判断是否选了权限
  const ids = [...treeRef.value!.getCheckedKeys(false)];
  if (ids.length <= 0) {
    ElMessage.error('请选择权限');
    return;
  }
  // 判断添加还是修改
  if (formData.value._id) {
    // 修改：
    updateRole({
      ...formData.value,
      permissions: ids
    });
  } else {
    // 添加：
    if (!formData.value.name) {
      ElMessage.error('角色名称不能为空');
      return;
    }
    if (!formData.value.group) {
      ElMessage.error('分组名称不能为空');
      return;
    }
    addRole({
      ...formData.value,
      permissions: ids
    });
  }
}

// 请求：添加角色
const addRole = async (data: any) => {
  // console.log(data);

  const res = await addRoleApi({
    ...data
  });
  // console.log(res);
  if (res.code == 200) {
    ElMessage.success('角色添加成功');
    onCancelBtnClick();
    getRoles();
  } else {
    ElMessage.error(res.message);
  }
}

// 请求：修改角色
const updateRole = async (data: any) => {
  const res = await updateRoleApi({
    ...data
  });
  // console.log(res);
  if (res.code == 200) {
    ElMessage.success('角色修改成功');
    onCancelBtnClick();
    getRoles();
  } else {
    ElMessage.error(res.message);
  }
}

// 事件：角色点击
const onRoleClick = (item: any) => {
  currentRole.value = item._id;
  treeBackShow(item);
}

// tree回显
function treeBackShow(row: any) {
  const ids = row.permissions.map((item: any) => item._id);
  nextTick(() => {
    treeRef.value?.setCheckedKeys([...ids]);
  })
  if (ids.length > 0) {
    isExpand.value = true;
  } else {
    isExpand.value = false;
  }
}

// 请求：获取角色数据
const getRoles = async () => {
  const res = await getRolesApi();
  // console.log(res);
  if (res.code == 200) {
    rolesData.value = res.data.rows;
  }
}

// ---------------------------

// 一键 展开、收起
function onExpandToggle() {
  isExpand.value = !isExpand.value;
}
watch([isExpand, treeRef], () => {
  const allNodes = treeRef.value?.store._getAllNodes();
  allNodes?.forEach(item => {
    item.expanded = isExpand.value;
  })
});

// --------------------------- Tree组件的父子联动勾选功能 -----------------------------

// 当用户点击Tree组件中的复选框时，触发该事件
const handleCheckChange = (node: any, checkedStatus: any) => {
  // 判断选中的数组中是否有当前点击的节点
  const checked = checkedStatus.checkedKeys.includes(node._id);
  // 进入if，说明用户当前的操作是【勾选】
  if (checked) {
    // 选中节点时处理子节点和父节点
    if (node.children?.length) {
      // 勾选所有子节点
      checkAllChildren(node, true);
    }
    checkAllParents(node);
  } else {
    // 取消节点时处理子节点
    if (node.children?.length) {
      checkAllChildren(node, false);
    }
  }
}
// 递归操作子节点
const checkAllChildren = (node: any, checked: boolean) => {
  node.children.forEach((child: any) => {
    treeRef.value?.setChecked(child._id, checked, false);
    if (child.children) checkAllChildren(child, checked);
  });
}
// 递归操作父节点
const checkAllParents = (node: any) => {
  let parent = getParentNode(node);
  while (parent) {
    treeRef.value?.setChecked(parent._id, true, false);
    parent = getParentNode(parent);
  }
}
// 父节点查找算法，返回目标节点的直接父节点
const getParentNode = (node: any) => {
  const findParent = (data: any[], targetId: string, parent: any): any => {
    for (const item of data) {
      if (item._id === targetId) return parent;
      if (item.children) {
        const found = findParent(item.children, targetId, item);
        if (found) return found;
      }
    }
    return null;
  }
  return findParent(permissionData.rows, node._id, null);
}

// ------------------------- Tree组件的父子联动勾选功能 --------------------------------
</script>

<style scoped lang="scss">
:deep(.el-text) {
  font-size: 13px;
}

.el-form-item {
  margin-bottom: 0;
}

.role-manage-box {
  box-sizing: border-box;

  .bGColor {
    background-color: #edf6ff;
  }

  /* 隐藏浏览器的滚动条 */
  ::-webkit-scrollbar {
    display: none;
  }

  .top-box {
    display: flex;

    button {
      height: 38px;

      font-size: 14px;
      color: #fff;

      background-color: #2984f8;

      outline: none;
      border: none;

      border-radius: 4px;

      padding: 0 10px;
    }

    .cancel-btn {
      min-width: 60px;

      flex: 0;

      border: 1px solid #ddd;
      background-color: #eee;
      color: #333;

      margin-left: 20px;
    }
  }

  .top {
    display: flex;
    justify-content: space-between;
    align-items: center;

    flex: 1;

    margin-bottom: 20px;

    span {
      font-size: 18px;
      color: #333;

      display: flex;
      align-items: center;
    }

    span::before {
      content: '';

      width: 5px;
      height: 22px;

      margin-right: 10px;

      background-color: #2984f8;

      border-radius: 3px;
    }
  }

  .role-content {

    display: flex;

    .role,
    .permission {
      // height: calc(100vh - 240px);

      border: 1px solid #F2F2F2;

      .text {
        color: #333;
        font-size: 16px;

        padding: 18px;
      }
    }

    .role {
      flex: 1;

      margin-right: 20px;
    }

    .permission {
      flex: 2;
    }

    .title-box {
      display: flex;
      justify-content: space-between;
      align-items: center;

      .add-role {
        font-size: 13px;
        color: #2984f8;

        cursor: pointer;
      }
    }

    .item {
      display: flex;
      justify-content: space-between;
      align-items: center;

      font-size: 13px;
      color: #333;

      padding: 10px 18px 10px 10px;

      span {
        width: calc(100% - 55px);

        cursor: pointer;
      }

      img {
        width: 16px;
        height: 16px;

        vertical-align: top;

        cursor: pointer;
      }

      .write-img {
        margin-right: 10px;
      }

      .icon-box {
        width: 50px;

        display: none;
      }
    }

    .item:hover {
      background-color: #edf6ff;
    }

    .item:hover .icon-box {
      display: block;
    }
  }
}
</style>